package com.ken.apollo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ken.apollo.commons.exception.ServiceException;
import com.ken.apollo.domain.bo.AdminLoginBo;
import com.ken.apollo.domain.bo.ChangePasswordBo;
import com.ken.apollo.domain.entity.AdminUser;
import com.ken.apollo.domain.vo.AdminUserVo;
import com.ken.apollo.mapper.AdminUserMapper;
import com.ken.apollo.service.AdminUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 管理员用户Service实现类
 *
 * @author Ken
 * @since 2025-08-25
 */
@Slf4j
@Service
public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser> implements AdminUserService {
    
    @Override
    public AdminUserVo login(AdminLoginBo loginBo, String clientIp) {
        // 参数验证
        if (StrUtil.isBlank(loginBo.getUsername()) || StrUtil.isBlank(loginBo.getPassword())) {
            throw new ServiceException("用户名和密码不能为空");
        }
        
        // 查询用户
        AdminUser user = getByUsername(loginBo.getUsername());
        if (user == null) {
            throw new ServiceException("用户名或密码错误");
        }
        
        // 检查用户状态
        if (!user.getStatus()) {
            throw new ServiceException("账号已被禁用，请联系管理员");
        }
        
        // 验证密码
        if (!BCrypt.checkpw(loginBo.getPassword(), user.getPassword())) {
            throw new ServiceException("用户名或密码错误");
        }
        
        // 更新最后登录信息
        updateLastLoginInfo(user.getId(), clientIp);
        
        // 转换为VO
        AdminUserVo userVo = new AdminUserVo();
        BeanUtil.copyProperties(user, userVo);
        userVo.setLastLoginTime(LocalDateTime.now());
        userVo.setLastLoginIp(clientIp);
        
        log.info("管理员登录成功：{}, IP：{}", user.getUsername(), clientIp);
        return userVo;
    }
    
    @Override
    public AdminUser getByUsername(String username) {
        if (StrUtil.isBlank(username)) {
            return null;
        }
        
        LambdaQueryWrapper<AdminUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AdminUser::getUsername, username);
        return this.getOne(wrapper);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean changePassword(Long userId, ChangePasswordBo changePasswordBo) {
        // 参数验证
        if (!changePasswordBo.getNewPassword().equals(changePasswordBo.getConfirmPassword())) {
            throw new ServiceException("两次输入的新密码不一致");
        }
        
        if (changePasswordBo.getNewPassword().length() < 6) {
            throw new ServiceException("新密码长度不能少于6位");
        }
        
        // 查询用户
        AdminUser user = this.getById(userId);
        if (user == null) {
            throw new ServiceException("用户不存在");
        }
        
        // 验证旧密码
        if (!BCrypt.checkpw(changePasswordBo.getOldPassword(), user.getPassword())) {
            throw new ServiceException("旧密码错误");
        }
        
        // 检查新密码是否与旧密码相同
        if (BCrypt.checkpw(changePasswordBo.getNewPassword(), user.getPassword())) {
            throw new ServiceException("新密码不能与旧密码相同");
        }
        
        // 更新密码
        user.setPassword(BCrypt.hashpw(changePasswordBo.getNewPassword(), BCrypt.gensalt()));
        boolean result = this.updateById(user);
        
        if (result) {
            log.info("管理员修改密码成功：{}", user.getUsername());
        }
        
        return result;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateLastLoginInfo(Long userId, String clientIp) {
        AdminUser user = new AdminUser();
        user.setId(userId);
        user.setLastLoginTime(LocalDateTime.now());
        user.setLastLoginIp(clientIp);
        this.updateById(user);
    }
}